#pragma once
#include <functional>
#include <thread>
#include "readerwriterqueue.h"
#include <vector>

template<typename T>
struct cscan_points
{
	T x;
	T y;
	T z;
	cscan_points() :x(T{}), y{ T{} }, z(T{}){}
	cscan_points(T x, T y, T z) :x(x), y{ y }, z(z){}
};

struct cscan_info
{
	cscan_points<size_t> size;	//voxel size
	cscan_points<double> scale;	//real space size
	int raster_direction{};	//0:x, others:y
};

#define INNER_VISION_CSCAN
/**
 * \brief Save C-scan data.
 * When required  number of lines are input, the file will be created automatically.
 * If you stop saving file, you must call 'cancel()'.
 * Otherwise destructor will not stop normally.
 */
class CscanFileBuilder
{
public:
	constexpr static  size_t max_buffer_size = 256;
private:

	std::string save_path_;
	cscan_info info_;
	bool canceled_ = false;
	int status_ = 0;		//0:not initialized, 1:saving, 2:saved;, 3:canceled, 4:error
	moodycamel::BlockingReaderWriterQueue < std::vector<float>, max_buffer_size> _queue{ 256 };
	std::string error_message_;
	std::thread _save_thread;

	void flip_endian(const uint32_t* original, uint32_t* fliped, int size) const;

	static void create_info_file(const std::string& path, const cscan_info& info);

public:
	CscanFileBuilder(std::string save_path, cscan_info cscan_info);
	~CscanFileBuilder();

	bool input_new_line(std::vector<float>& newline);
	inline size_t get_buffer_size() const
	{
		return _queue.size_approx();
	}
	/**
	 * \brief status
	 * \return 0:not initialized, 1:saving, 2:saved;, 3:canceled, 4:error
	 */
	inline  int get_status() const
	{
		return status_;
	}
	inline std::string get_error_message() const
	{
		return std::string{ error_message_ };
	}
	inline void cancel()
	{
		if (!canceled_)
			canceled_ = true;
	}
};